package com.scwatch.core.web.back;

import com.alibaba.fastjson.JSONObject;
import com.scwatch.common.office.ExcelUtil;
import com.scwatch.common.upload.UploadResult;
import com.scwatch.common.web.Servlets;
import com.scwatch.core.constant.Constants;
import com.scwatch.core.domain.*;
import com.scwatch.core.service.CodeDevService;
import com.scwatch.core.service.InviteService;
import com.scwatch.core.service.OperationLogService;
import com.scwatch.core.support.Backends;
import com.scwatch.core.support.Context;
import com.scwatch.core.support.UploadHandler;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.util.CollectionUtils;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.scwatch.core.constant.Constants.*;

/**
 * class_name: InviteController
 * describe: 邀请码管理
 * creat_user: HotSun
 * creat_date: 2017/9/27  09:53
 **/
@Controller
@RequestMapping("/core/invite_code")
public class InviteController {

    private static final Logger logger = LoggerFactory.getLogger(InviteController.class);

    @Autowired
    private InviteService inviteService;

    @Autowired
    private OperationLogService logService;

    @Autowired
    private CodeDevService codeDevService;

    @Autowired
    protected UploadHandler uploadHandler;

    @Autowired
    protected MessageSource messageSource;


    /**
     * 查询邀请码
     * @param pageable 分页对象
     * @param request
     * @param modelMap
     * @return 结果页面
     */
    @RequiresPermissions("core:invite_code:list")
    @RequestMapping("list.do")
    public String list(@PageableDefault(sort ={"devNum","id"} , direction = Sort.Direction.DESC) Pageable pageable,HttpServletRequest request, Model modelMap) {

        Map<String, String[]> params = Servlets.getParamValuesMap(request,Constants.SEARCH_PREFIX);

        Integer siteId = Context.getCurrentSiteId();
        params.put("EQ_site.id",new String[]{siteId.toString()});
        Page<Invite> pagedList = inviteService.findAll(params, pageable);

        modelMap.addAttribute("pagedList", pagedList);
        return "core/invite_code/invite_code_list";
    }

    /**
     * 设备信息查询
     * @param pageable 分页对象
     * @param request
     * @param modelMap
     * @return 结果页面
     */
    @RequiresPermissions("core:code_dev:list")
    @RequestMapping("code_dev_list.do")
    public String codeDevList(@PageableDefault(sort = "time", direction = Sort.Direction.DESC) Pageable pageable,HttpServletRequest request, Model modelMap) {

        Map<String, String[]> params = Servlets.getParamValuesMap(request,Constants.SEARCH_PREFIX);

        String codeId = request.getParameter("codeId");
        if(StringUtils.isNotBlank(codeId)){
            params.put("EQ_codeId.id", new String[]{codeId.toString()});
            modelMap.addAttribute("codeId", codeId);
        }

        Page<CodeDev> pagedList=codeDevService.findAll(params,pageable);

        modelMap.addAttribute("pagedList", pagedList);
        return "core/invite_code/code_dev_list";
    }

    @RequiresPermissions("core:invite_code:create")
    @RequestMapping("create.do")
    public String create(Integer position, HttpServletRequest request, org.springframework.ui.Model modelMap) {

        modelMap.addAttribute("position", position);

        modelMap.addAttribute(OPRT, CREATE);

        return "core/invite_code/invite_code_form";

    }

    @RequiresPermissions("core:invite_code:edit")
    @RequestMapping("edit.do")
    public String edit(Integer id, Integer position,
                       HttpServletRequest request, org.springframework.ui.Model modelMap) {

        Invite bean = inviteService.get(id);

        Map<String, String[]> params = Servlets.getParamValuesMap(request,
                Constants.SEARCH_PREFIX);

        modelMap.addAttribute("bean", bean);

        modelMap.addAttribute("position", position);

        modelMap.addAttribute(OPRT, EDIT);

        return "core/invite_code/invite_code_form";
    }

    /**
     * 保存邀请码
     * @param id
     * @param position
     * @param bean 邀请码对象
     * @param request
     * @param redirect
     * @param ra
     * @return 结果页面
     */
    @RequiresPermissions("core:invite_code:save")
    @RequestMapping("save.do")
    public String save(Integer id, Integer position, Invite bean,
                       HttpServletRequest request, String redirect, RedirectAttributes ra) {
        String ip = Servlets.getRemoteAddr(request);
        Site site = Context.getCurrentSite();
        User user = Context.getCurrentUser();
        bean.setSite(site);
        bean.setUser(user);
        bean.setUdpateDate(new Date());
        bean.setDevNum(0);

        Map<String, String[]> paraMap =new HashMap<>();
        paraMap.put("EQ_invitationCode",new String[]{bean.getInvitationCode()});
        paraMap.put("EQ_site.id",new String[]{site.getId().toString()});
        PageRequest pageable=new PageRequest(0,100,new Sort(Sort.Direction.DESC,"id"));
        Page<Invite> pagedList=inviteService.findAll(paraMap,pageable);

        paraMap =new HashMap<>();
        paraMap.put("EQ_city",new String[]{bean.getCity()});
        paraMap.put("EQ_site.id",new String[]{site.getId().toString()});
        Page<Invite> paged2List=inviteService.findAll(paraMap,pageable);

        if(pagedList.getTotalElements()>0 || paged2List.getTotalElements()>0){
            ra.addFlashAttribute(MESSAGE,INVITE_EXIST);
            return "redirect:create.do";
        }

        bean = inviteService.save(bean);

        logService.operation("core:invite_code:save", bean.getInvitationCode(), null, bean.getId(), ip, user.getId(), site.getId());

        ra.addFlashAttribute(MESSAGE, SAVE_SUCCESS);

        if (Constants.REDIRECT_LIST.equals(redirect)) {

            ra.addAttribute("position", position);

            return "redirect:list.do";

        }
        if(Constants.REDIRECT_EDIT.equals(redirect)){

            ra.addAttribute("id", bean.getId());

            return "redirect:edit.do";

        }else{
            return "redirect:create.do";
        }
    }

    /**
     * 修改邀请码
     * @param position
     * @param redirect
     * @param bean 邀请码对象
     * @param request
     * @param ra
     * @return 结果页面
     */
    @RequiresPermissions("core:invite_code:update")
    @RequestMapping("update.do")
    public String update( Integer position, String redirect, Invite bean,
                          HttpServletRequest request, RedirectAttributes ra) {
        String ip = Servlets.getRemoteAddr(request);

        Site site = Context.getCurrentSite();

        User user = Context.getCurrentUser();

        Backends.validateDataInSite(bean, site.getId());

        bean.setUser(user);
        bean.setSite(site);
        bean.setUdpateDate(new Date());


        Map<String, String[]> paraMap =new HashMap<>();
        paraMap.put("EQ_invitationCode",new String[]{bean.getInvitationCode()});
        paraMap.put("NOTEQ_id",new String[]{bean.getId().toString()});
        paraMap.put("EQ_site.id",new String[]{site.getId().toString()});
        PageRequest pageable=new PageRequest(0,100,new Sort(Sort.Direction.DESC,"id"));
        Page<Invite> pagedList=inviteService.findAll(paraMap,pageable);

        paraMap =new HashMap<>();
        paraMap.put("NOTEQ_id",new String[]{bean.getId().toString()});
        paraMap.put("EQ_city",new String[]{bean.getCity()});
        paraMap.put("EQ_site.id",new String[]{site.getId().toString()});
        Page<Invite> paged2List=inviteService.findAll(paraMap,pageable);

        if(pagedList.getTotalElements()>0 || paged2List.getTotalElements()>0){
            ra.addAttribute("id", bean.getId());
            ra.addFlashAttribute(MESSAGE,INVITE_EXIST);
            return "redirect:edit.do";
        }
        bean.setDevNum(inviteService.get(bean.getId()).getCodeDevs().size());
        bean = inviteService.update(bean);


        logService.operation("core:invite_code:update", bean.getInvitationCode(), null, bean.getId(), ip, user.getId(), site.getId());

        ra.addFlashAttribute(MESSAGE, SAVE_SUCCESS);

        if (Constants.REDIRECT_LIST.equals(redirect)) {

            ra.addAttribute("position", position);

            return "redirect:list.do";

        }
        if(Constants.REDIRECT_CREATE.equals(redirect)){
            return "redirect:create.do";
        }else {
            ra.addAttribute("id", bean.getId());
            return "redirect:edit.do";
        }
    }

    /**
     * 删除邀请码
     * @param ids 邀请码id
     * @param request
     * @param ra
     * @return
     */
    @RequiresPermissions("core:invite_code:delete")
    @RequestMapping("delete.do")
    public String delete(Integer[] ids, HttpServletRequest request,
                         RedirectAttributes ra) {

        String ip = Servlets.getRemoteAddr(request);

        Site site = Context.getCurrentSite();

        User user = Context.getCurrentUser();

        validateIds(ids, site.getId());

        Invite []invites=inviteService.delete(ids);
        for (Invite invite : invites) {
            logService.operation("core:invite_code:delete", invite.getInvitationCode(), null, invite.getId(), ip, user.getId(), site.getId());
        }
        ra.addFlashAttribute(MESSAGE, DELETE_SUCCESS);

        return "redirect:list.do";
    }

    /**
     * 获取MultipartFile
     * @param request
     * @return
     */
    protected MultipartFile getMultipartFileInfo(HttpServletRequest request){
        return getMultipartFile(request);
    }

    private MultipartFile getMultipartFile(HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        if (CollectionUtils.isEmpty(fileMap)) {
            throw new IllegalStateException("No upload file found!");
        }
        return fileMap.entrySet().iterator().next().getValue();
    }

    @RequiresPermissions("core:invite_code:upload")
    @RequestMapping("upload.do")
    public String upload(Integer position, HttpServletRequest request, org.springframework.ui.Model modelMap) {
        return "core/invite_code/invite_code_upload";

    }

    /**
     * 上传邀请码
     * @param request
     * @param response
     * @throws Exception
     */
    @RequiresPermissions("core:invite_code:upload")
    @RequestMapping(value = "uploadInvitecode.do", method = RequestMethod.POST)
    public void uploadInvitecode(HttpServletRequest request,HttpServletResponse response) throws Exception {
        MultipartFile multipartFile = getMultipartFileInfo(request);
        //验证
        ExcelUtil.checkFile(multipartFile);
        Site site = Context.getCurrentSite();
        User user=Context.getCurrentUser();
        String ip = Servlets.getRemoteAddr(request);
        UploadResult result = new UploadResult();
        Locale locale = RequestContextUtils.getLocale(request);
        result.setMessageSource(messageSource, locale);
//        uploadHandler.upload(multipartFile, Uploader.FILE, site, user.getId(), ip, result, null, null, null, null, null,null, null, null);
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
        logService.operation("core:invite_code:upload",multipartFile.getName(), null,null, ip, user.getId(), site.getId());
        //获取上传的excel文件

        try {
            List<Code> list = ExcelImportUtil.importExcel(multipartFile.getInputStream(), Code.class,params);
            List<Invite> beans=new ArrayList<>();
            if(list!=null && list.size()>0){
                for(Code code:list){
                   if(code!=null && StringUtils.isNotBlank(code.getCode())){}{
                        Map<String, String[]> paraMap =new HashMap<>();
                        paraMap.put("EQ_invitationCode",new String[]{code.getCode()});
                        paraMap.put("EQ_site.id",new String[]{site.getId().toString()});
                        PageRequest pageable=new PageRequest(0,100,new Sort(Sort.Direction.DESC,"id"));
                        Page<Invite> pagedList=inviteService.findAll(paraMap,pageable);

                        paraMap =new HashMap<>();
                        paraMap.put("EQ_city",new String[]{code.getCity()});
                        paraMap.put("EQ_site.id",new String[]{site.getId().toString()});
                        Page<Invite> paged2List=inviteService.findAll(paraMap,pageable);
                        if(pagedList.getTotalElements()>0 || paged2List.getTotalElements()>0){
                             continue;
                        }
                        Invite bean=new Invite();
                        bean.setCity(code.getCity());
                        bean.setInvitationCode(code.getCode());
                        bean.setSite(site);
                        bean.setUser(user);
                        bean.setUdpateDate(new Date());
                        bean.setDevNum(0);
                        beans.add(bean);
                   }
                }
                inviteService.saveList(beans);
                result.setMessage("上传成功!");
            }
        } catch (Exception e) {
            result.setMessage("上传失败，请重试!");
            result.setError(e.getMessage());
            e.printStackTrace();
            logger.error("upload invite fail");
        }
        Servlets.writeHtml(response, JSONObject.toJSONString(result));
    }

    /**
     * 导出邀请码
     * @param request
     * @param response
     */
    @RequestMapping("/export.do")
    public @ResponseBody void export(HttpServletRequest request,HttpServletResponse response){
        response.setContentType("application/binary;charset=UTF-8");
        try{
            Map<String, String[]> params = Servlets.getParamValuesMap(request,Constants.SEARCH_PREFIX);
            Integer siteId = Context.getCurrentSiteId();
            params.put("EQ_site.id",new String[]{siteId.toString()});
            PageRequest pageable=new PageRequest(0,100000,new Sort(Sort.Direction.DESC,"devNum","id"));
            Page<Invite> pagedList = inviteService.findAll(params, pageable);
            List<Invite> inviteList=pagedList.getContent();
            ServletOutputStream out=response.getOutputStream();
            String fileName=new String(("invite_code_"+ new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())).getBytes(),"UTF-8");
            response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");
            String[] titles = { "城市", "邀请码", "设备数"};
            inviteService.export(titles, out,inviteList);
        } catch(Exception e){
            e.printStackTrace();
        }
    }

    private void validateIds(Integer[] ids, Integer siteId) {

        for (Integer id : ids) {

            Backends.validateDataInSite(inviteService.get(id), siteId);
        }
    }

}
